/**
 * 初次渲染步骤
 */

// 1. 从 Routes 组件中获取所有的 `children` 子元素
// 2. 调用 createRoutesFromChildren(children) 将 children 子元素转换成 routes 配置数组
//   1. routes [{path: 当前路由路径, element: 路由需要渲染的虚拟DOM, children: 当前路由的子路由}]
// 3. 调用并返回 useRoutes(routes)
//   1. 调用 useLocation 从上下文中获取 location 位置对象
//   2. 从 location 位置对象中获取 pathname 属性 其中值是浏览器地址栏路径
//   3. 调用 matchRoutes(routes, pathname) 匹配路径 并获取匹配结果 matches
//     1. 调用 flattenRoutes(routes) 将配置数组打平为 branches 路径分支数组
//       1. branches [{routePath: 当前路由被访问的完整路径, routeMetas: [{祖先路由元数据},{route: 路由对象,  childrenIndex: 当前路由在兄弟路径的索引}], score: 当前路由分支的权重分数}]
//       2. 给每个一级路由的访问路径头部添加一个 / ， 如果有重复的 / 则只会保存一个 /
//     2. 调用 rankRoutesBranches(branches) 对路由分支组成的数组进行排序
//     3. 声明一个 matches = null 变量 用于保存匹配的结果
//     4. 遍历 branches 路由分支数组 对每一个路由分支数组执行
//       1. 调用 matchRouteBranch(路由分支, 浏览器地址路径) 并将返回值赋值给 matches
//         1. 从路由分支中获取 路由元数据组成的 routeMetas 数组 
//         2. 声明一个 matchedPathname = '' 用于保存已经匹配过的路径
//         3. 声明一个 matches = [] 用于保存匹配的结果
//         4. 声明一个 matchedParams = {} 用于保存动态路由参数
//         5. 遍历路由元数据组成的数组
//           1. 获取路由元数据对象中的 route 路由对象
//           2. 声明一个 end 变量 用于判断当前路由元数据是不是路由分支元数据数组中最后一个元数据
//           3. remainingPathname 值是剩下需要匹配的路径
//           4. 调用 matchPath({path: route.path, end}, remainingPathname) 获取 match 匹配的结果
//             1. 调用 compilePath 编译正则返回一个数组 [匹配浏览器地址的正则表达式, 动态路径参数数组[]]
//             2. pathname.match(/^\/\/*$/) 调用浏览器地址路径的 match 方法匹配成功
//             3. 返回 { params: 匹配的路径参数组成的对象, matchedPathname: 匹配的路径 }
//           5. Object.assign({}, matchedParams, match.params) 合并动态路径参数到 matchedParams 中
//           6. matches.push({route: 路由对象, params: 动态路径参数对象}) 保存匹配的结果
//           7. matchedPathname = joinPaths([matchedPathname, match.matchedPathname]) 将以前匹配的路径和当前匹配的路径合并保存到 matchedPathname 变量中
//     5. 返回 matches
//   4. 调用并返回 _renderMatches(matches) 渲染匹配的结果 [{route: 路由对象, params: 动态路径参数对象}]
